﻿#region All usings
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using senSimulator.DrawableComponents.Vehicles;
#endregion


namespace senSimulator.DrawableComponents.TrafficLights.Types
{
    class TrafficLightForPedestrians : TrafficLight
    {
        // Current cross road direction for switching pedestrians from traffic light
        private CrossRoadDirection _crossroadDirection;
        private Random _randomGenerator = new Random();


        /// <summary>
        /// Constructor
        /// </summary>
        public TrafficLightForPedestrians(Game game, Vector2 spawnPosition, Texture2D[] textureNames, Vector2[] textureCenters, int posX, int posY, int rotationInDegrees, string trafficLightID, int distanceToTrafficLight, CrossRoadDirection crossRoadDirection)
            : base(game, spawnPosition, textureNames, textureCenters, posX, posY, rotationInDegrees, trafficLightID, distanceToTrafficLight)
        {
            _crossroadDirection = crossRoadDirection;
        }


        /// <summary>
        /// Constructor (overload)
        /// </summary>
        public TrafficLightForPedestrians(Game game, Vector2 spawnPosition, Texture2D[] textureNames, Vector2[] textureCenters, int posX, int posY, int rotationInDegrees, SpriteEffects spriteEffect, string trafficLightID, int distanceToTrafficLight, CrossRoadDirection crossRoadDirection)
            : base(game, spawnPosition, textureNames, textureCenters, posX, posY, rotationInDegrees, spriteEffect, trafficLightID, distanceToTrafficLight)
        {
            _crossroadDirection = crossRoadDirection;
        }


        // <summary>.
        /// Traffic light states for the Pedestrians light
        /// </summary>
        /// <param name="state">New state of the traffic light</param>
        public override void ChangeTrafficLightState(int state)
        {
            switch (state)
            {
                case 0:     // OFF                
                    SwitchOff();
                    break;
                case 1:     // GREEN
                    _trafficLightState = state + 1;
                    _blinking = false;
                    _errorAndOffstate = false;
                    break;
                case 2:     // GREEN blinking
                    _trafficLightState = state;
                    _blinking = true;
                    _errorAndOffstate = false;
                    break;
                case 3:     // RED
                    _trafficLightState = state - 2;
                    _blinking = false;
                    _errorAndOffstate = false;
                    break;
                case 7:     // Error
                    _trafficLightState = state - 7;
                    _errorAndOffstate = true;
                    break;
                default:    // NOT SUPPORTED
                    Console.WriteLine("Pedestrian traffic light does not support state number: " + state);
                    break;
            }
        }


        /// <summary>
        /// Add a pedestrian item to the traffic (light) queue
        /// </summary>
        /// <param name="traffic">A traffic type</param>
        public override void AddPedestrian(Traffic traffic, CrossRoadDirection toWardsCrossRoad, TrafficLight[] usedTrafficLights, bool spawned)
        {
            // If the pedestrian has already spawned, it only needs to be transfered.
            if (spawned)
            {
                // Move the pedestrian to the first way point
                lock (_trafficLightQueue)
                {
                    _trafficLightQueue.Add(traffic);
                }
                _trafficLightQueueLength++;
            }
            else
            {
                // Spawn the pedestrian at a random position (for nice and cool effects, yeey!)
                int spawnDifference = 8;
                int randomX = _randomGenerator.Next(-spawnDifference, spawnDifference);
                int randomY = _randomGenerator.Next(-spawnDifference, spawnDifference);

                traffic.SetPosition(_texturePosition.X + _spawnPosition.X + randomX, _texturePosition.Y + _spawnPosition.Y + randomX, false);

                // Create all way points for the traffic
                Vector2 _firstTrafficLight = new Vector2(_texturePosition.X + _distanceVectorToTrafficLight.X + randomX, _texturePosition.Y + _distanceVectorToTrafficLight.Y + randomY);
                Vector2 _secondTrafficLight = new Vector2(usedTrafficLights[0].GetPosition().X + _distanceVectorToTrafficLight.X + randomX, usedTrafficLights[0].GetPosition().Y + _distanceVectorToTrafficLight.Y + randomY);
                Vector2 _otherSide = new Vector2(usedTrafficLights[1].GetPosition().X + _distanceVectorToTrafficLight.X + randomX, usedTrafficLights[1].GetPosition().Y + _distanceVectorToTrafficLight.Y + randomY);
                Vector2 _outSideWorld = new Vector2(usedTrafficLights[1].GetPosition().X + _spawnPosition.X + _distanceVectorToTrafficLight.X + randomX, usedTrafficLights[1].GetPosition().Y + _spawnPosition.Y + _distanceVectorToTrafficLight.Y + randomY);

                // Set the way points for the car
                Vector2[] wayPoints = new Vector2[] 
                {
                    _firstTrafficLight,
                    _secondTrafficLight,
                    _otherSide,
                    _outSideWorld
                };
                traffic.SetWayPoints(wayPoints);

                // Set the traffic light to move towards to
                Pedestrian pedestrian = (Pedestrian)traffic;
                pedestrian.SetSecondTrafficLight(usedTrafficLights[0]);

                // Move the pedestrian to the first way point
                lock (_trafficLightQueue)
                {
                    _trafficLightQueue.Add(pedestrian);
                }
                _trafficLightQueueLength++;
            }
        }


        /// <summary>
        /// Move a bike based on the different states
        /// </summary>
        public override void MoveTraffic(Controller controller)
        {
            for (int i = 0; i < _trafficLightQueueLength; i++)
            {
                // Get the pedestrian and check if it has reached the end
                Pedestrian pedestrian;
                lock (_trafficLightQueue)
                {
                    pedestrian = (Pedestrian)_trafficLightQueue.ElementAt(i);
                }
                if (pedestrian.IsFinished())
                {
                    RemoveTraffic(pedestrian);
                    break;
                }


                // Check if the pedestrian hits the sensor
                if (pedestrian.GetCurrentWayPoint() == 1 && !pedestrian.SensorTriggered() && pedestrian.GetPosition() == pedestrian.GetFirstWayPoint())
                {
                    pedestrian.SetSensorTriggered(true);
                    controller.SendSensorTriggerToController(this.getName(), 100, pedestrian.GetTo());
                }

                // Check if the pedestrian needs to switch from traffic light (if it has reached the center)
                if (!pedestrian.HasReachedCenter() && pedestrian.GetCurrentWayPoint() == 2)
                {
                    pedestrian.SetHasReachedCenter(true);
                    pedestrian.SetCrossedTrafficLight(false);
                    RemoveTraffic(pedestrian);
                    _crossroadDirection.SwitchPedestrianFromTrafficLight(pedestrian, this, controller);
                }
                else // Else, keep on walking
                {
                    // If green light, keep on moving!
                    if ((_trafficLightState == 2 && !_blinking) || _errorAndOffstate)
                    {
                        pedestrian.Move();
                        if (!pedestrian.CrossedTrafficLight() && pedestrian.GetCurrentWayPoint() != 0)
                            pedestrian.SetCrossedTrafficLight(true);
                    }
                    // Else if the pedestrian has crossed the traffic light and it's blinking OR red, also keep on moving...
                    else if (pedestrian.CrossedTrafficLight() && (_blinking || _trafficLightState == 1))
                    {
                        pedestrian.Move();
                    }
                    // Else if the pedestrians are still walking towards the first or the last way point, keep on moving! :)
                    else if (pedestrian.GetCurrentWayPoint() == 0 || pedestrian.GetCurrentWayPoint() == 3)
                        pedestrian.Move();
                    else // In all other cases, stop! Don't even think about moving.
                        pedestrian.Stop();
                }
            }
        }
    }
}